<?php

namespace App\Models\Traits;

use App\Exceptions\CategoryNotFound;
use App\Lib\RoomAnalyze;

trait RoomInfo
{
    protected $category = '';

    protected $roomDetail;

    public function setCategory(string $category)
    {
        $this->category = $category;
        return $this;
    }

    abstract protected function getUri();

    protected function getRoomDetail($field = null)
    {
        if (!empty($this->roomDetail)) {
            $response = $this->roomDetail;
        } else {
            $response = $this->curlGet($this->getUri());
            if (false !== $response) {
                $response = $this->formatRoom($response, true);
            }
            $this->roomDetail = $response;
        }
        if (!empty($field)) {
            if (isset($response[$field])) {
                return $response[$field];
            } else {
                return false;
            }
        }
        return $response;
    }

    // todo 合并列表和单房间获取
    protected function formatRoom(string $response, bool $detail): array
    {
        $result = [];
        if (config()->has('platform.' . $this->getPlatformName())) {
            $fields = $this->getPlatformConfig('field');
            $containers = $this->getPlatformConfig('containers');
            // 没有api的分析网页实现
            if (is_string($containers)) {
                $result = $this->formatRoomByClass($containers);
            } else {
                // 通过api获取数据
                $response = json_decode($response, true);
                // 移除外层包装
                foreach ($containers as $container) {
                    $response = $response[$container];
                }
                // 是否为单房间
                if ($detail && count($response) > 1) {
                    $response = [$response];
                }
                // 遍历结果按照配置文件生成统一格式数组
                foreach ($response as $item) {
                    $res = [];
                    // 遍历字典
                    foreach ($fields as $field => $value) {
                        if (is_array($value)) {
                            // 需要替换变量
                            $str = '';
                            foreach ($value as $val) {
                                if (strpos($val, ':') === 0) {
                                    $str .= $item[substr($val, 1)];
                                } else {
                                    $str .= $val;
                                }
                            }
                            $res[$field] = $str;
                        } elseif (strpos($value, '.') !== false) {
                            // 分析.号分隔的多维数组
                            $value = explode('.', $value);
                            $new_item = $item;
                            foreach ($value as $val) {
                                $new_item = $new_item[$val];
                            }
                            $res[$field] = $new_item;
                        } else {
                            $res[$field] = $item[$value];
                        }
                    }
                    // 添加平台名以生成key
                    $res['platform'] = $this->getPlatformName();
                    // 添加跳转临时key
                    try {
                        $res['key'] = $this->cacheRoomInfo($res);
                    } catch (\Exception $exception) {
                        logger()->warning($exception->getMessage());
                        continue;
                    }
                    $result[] = $res;
                }
                // 单房间只需要第一个结果
                if ($detail && 1 === count($response)) {
                    $result = current($result);
                }
            }
        }
        return $result;
    }

    protected function formatRoomByClass(string $containers): array
    {
        $result = [];
        $containers = app($containers);
        if ($containers instanceof RoomAnalyze) {
            $result = $containers->getRoomInfo($this->getUri());
        }
        // 添加跳转临时key
        try {
            $result['platform'] = $this->getPlatformName();
            $result['key'] = $this->cacheRoomInfo($result);
        } catch (\Exception $exception) {
            logger()->warning($exception->getMessage());
        }
        return $result;
    }

    abstract protected function getPlatformName(): string;

    protected function getRoomList(string $response): array
    {
        if (config()->has('platform.' . $this->getPlatformName())) {
            $fields = $this->getPlatformConfig('field');
            $containers = $this->getPlatformConfig('containers');
            $response = json_decode($response, true);
            foreach ($containers as $container) {
                $response = $response[$container];
            }
            foreach ($response as $item) {
                $res = [];
                foreach ($fields as $field => $value) {
                    if (is_array($value)) {
                        $str = '';
                        foreach ($value as $val) {
                            if (strpos($val, ':') === 0) {
                                $str .= $item[substr($val, 1)];
                            } else {
                                $str .= $val;
                            }
                        }
                        $res[$field] = $str;
                    } elseif (strpos($value, '.') !== false) {
                        $value = explode('.', $value);
                        $new_item = $item;
                        foreach ($value as $val) {
                            $new_item = $new_item[$val];
                        }
                        $res[$field] = $new_item;
                    } else {
                        $res[$field] = $item[$value];
                    }
                }
                $res['platform'] = $this->getPlatformName();
                try {
                    $res['key'] = $this->cacheRoomInfo($res);
                } catch (\Exception $exception) {
                    logger()->warning($exception->getMessage());
                    continue;
                }
                $result[] = $res;
            }
        }
        return $result ?? [];
    }

    protected function getPlatformConfig($type)
    {
        return config("platform.{$this->getPlatformName()}.list.$type", []);
    }

    /**
     * @author kuddy
     * @param array $roomInfo
     * @return string
     * @throws \Exception
     */
    protected function cacheRoomInfo(array $roomInfo): string
    {
        $key = sha1($roomInfo['platform'] . $roomInfo['id']);
        if (!cache()->has($key)) {
            unset($roomInfo['pop']);
            unset($roomInfo['src']);
            unset($roomInfo['name']);
            cache()->forever($key, $roomInfo);
        }
        return $key;
    }

    /**
     * @author kuddy
     * @param string $category
     * @return string
     * @throws CategoryNotFound
     */
    protected function transCategory(string $category): string
    {
        $category_map = config('category.' . $this->getPlatformName(), []);
        if (!isset($category_map[$category])) {
            throw new CategoryNotFound("category:$category not found in {$this->getPlatformName()} platform");
        }
        return $category_map[$category];
    }
}